package cn.loyle.excel;

import cn.loyle.exception.LpExcelException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Penguin on 2017/5/19.
 */
public class ExcelUtil {
    private static POIFSFileSystem fs = null;
    private static HSSFWorkbook wb = null;

    private ExcelUtil(){}

    /**
     *
     * @param file
     * @param clazz
     * @param <T>
     * @return List<T>
     * @throws LpExcelException
     */
    public static <T> List<T> importExcel(String file, Class clazz) throws LpExcelException {
        try {
            return importExcel(new FileInputStream(file),clazz);
        } catch (FileNotFoundException e) {
            throw new LpExcelException(e);
        }
    }

    /**
     *
     * @param file
     * @param clazz
     * @param map
     * @param <T>
     * @return List<T>
     * @throws LpExcelException
     */
    public static <T> List<T> importExcel(File file, Class clazz, Map<String,String> map) throws LpExcelException {
        try {
            return importExcel(new FileInputStream(file),clazz,map);
        } catch (FileNotFoundException e) {
            throw new LpExcelException(e);
        }
    }

    /**
     *
     * @param is
     * @param clazz
     * @param <T>
     * @return List<T>
     * @throws LpExcelException
     */
    public static <T> List<T> importExcel(InputStream is, Class clazz) throws LpExcelException {
        Map<String,String> map = new HashMap<String, String>();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if(method.toString().toLowerCase().contains("set")){
                String methodName = method.getName();
                String name = methodName.substring(3,methodName.length());
                map.put(name.toLowerCase(),name);
            }
        }
        return importExcel(is,clazz,map);
    }

    /**
     *
     * @param is
     * @param clazz
     * @param map
     * @param <T>
     * @return  List<T>
     * @throws LpExcelException
     */
    public static <T> List<T> importExcel(InputStream is, Class clazz, Map<String,String> map) throws LpExcelException {
        try {
            fs = new POIFSFileSystem(is);
            wb = new HSSFWorkbook(fs);
            HSSFSheet sheet = wb.getSheetAt(0);
            Map<Integer, Method> methodMap = getTittle(sheet, clazz, map);
            return getTexts(sheet,methodMap,clazz);
        } catch (Exception e){
            throw new LpExcelException(e);
        }finally {
            try{
                if(fs!=null) {
                    fs.close();
                }
                if(wb!=null) {
                    wb.close();
                }
                if(is!=null) {
                    is.close();//不确定这里要不要关
                }
            } catch (IOException e) {
//                throw new LpExcelException("can't close io because"+e);
                e.printStackTrace();
            }
        }

    }
    //获取表头
    private static Map<Integer,Method> getTittle(HSSFSheet sheet, Class clazz,Map<String,String> map) {
        Map<Integer,Method> methodMap = new HashMap<Integer, Method>();
        HSSFRow row = sheet.getRow(0);
        int colNum = row.getPhysicalNumberOfCells();
        for (int i = 0; i < colNum; i++) {
            HSSFCell cell = row.getCell(i);
            String s = cell.toString().toLowerCase();
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if(method.toString().toLowerCase().contains("set"+map.get(s).toLowerCase())){
                    methodMap.put(i,method);
                }
            }
        }
        return methodMap;
    }

    //获取Excel内容
    private static <T>  List<T> getTexts(HSSFSheet sheet, Map<Integer, Method> methodMap,Class clazz) throws LpExcelException{
        List<T> list = new ArrayList<T>();
        int lastRowNum = sheet.getLastRowNum();

        for (int i = 1;i<=lastRowNum;i++){
            Object obj;
            try {
                obj = clazz.newInstance();
            } catch (Exception e) {
                throw new LpExcelException("can not instance " +clazz.getName()+ " because"+e);
            }
            HSSFRow row = sheet.getRow(i);
            int colNum = row.getPhysicalNumberOfCells();
            for (int j = 0; j < colNum; j++) {
                HSSFCell cell = row.getCell(j);
                String s = cell.toString();
                Method method = methodMap.get(j);
                String type =method.getParameterTypes()[0].toString().toLowerCase();
                try {
                    if (type.contains("string")) {//String
                        method.invoke(obj, s);
                    } else if (type.contains("float")) {//Float
                        method.invoke(obj, Float.valueOf(s));
                    } else if (type.contains("double")) {//Double
                        method.invoke(obj, Double.valueOf(s));
                    } else if (type.contains("int")) {//Integer
                        method.invoke(obj, Integer.valueOf(s));
                    } else {
                        throw new LpExcelException("暂不支持" + type + "类型");
                    }
                }catch (Exception e) {
                    throw new LpExcelException(e);
                }

            }
            list.add((T)obj);
        }
        return list;
    }
}
